<?php defined('SYSPATH') or die('No direct script access.');

/**
 * Enter description here...
 *
 * @package    	Kohadmin
 * @subpackage	Libraries
 * @author     	Thomas Filius
 * @copyright  	(c) 2009 Nobis Stultius IT
 * @license		GNU Lesser General Public License 3
 * @version		$Id $
 */
class KohadminIndex_Core
{
	public $table_type = "normal";
	public $title = NULL;
	
	private $descriptors = FALSE;
	private $descriptors_ignore = array();

	private $filterquery = NULL;
	private $filter_ignores = array();

	private $field_actions = array();
	private $actions = NULL;

	public $globals = array();
	public $defaults = array();

	private $orm = NULL;
	private $orm_method = NULL;

	/**
	 * Constructor. Setup library and initialises settings
	 *
	 */
	public function __construct($modelname = NULL, $descriptors = NULL)
	{
		$this->_getSettings();
		$this->descriptors = $descriptors;
		$this->orm = ORM::factory($modelname);
	}

	/**
	 * Factory method. Creates and returns a new KohadminIndex object
	 *
	 * @param string $modelname
	 * @return KohadminIndex
	 */
	public static function factory($modelname = NULL, $descriptors = NULL)
	{
		return new KohadminIndex($modelname, $descriptors);
	}

	/**
	 * __toString method. Returns the layout and data of KohadminIndex
	 *
	 * @return string
	 */
	public function __toString()
	{
		return $this->get();
	}

	/**
	 * _getSettings method. Loads config `kohadminindex`
	 *
	 */
	private function _getSettings()
	{
		$this->defaults = Kohana::config('kohadminindex.defaults');
		$this->globals = Kohana::config('kohadminindex.globals');
	}

	/**
	 * Returns an array with fields that should be used as descriptors
	 */
	private function _descriptors_array ()
	{
		// no manual input of descriptors, get from DB
		if ( ! $this->descriptors) {
			$this->descriptors = array_keys($this->orm->table_columns);
		}
		$t = array();
		//die(Kohana::debug($this->descriptors));
		foreach ($this->descriptors as $descriptor) {
			// ignore this descriptor?
			if ( in_array($descriptor, $this->descriptors_ignore))
				continue;

			$t[] = $descriptor;
		}
		return $t;
	}

	private function _searchable_array ()
	{
		$t = array();

		foreach ($this->_descriptors_array() as $descriptor) {
			if ( ! in_array($descriptor, $this->filter_ignores)) {
				$t[] = $descriptor;
			}
		}
		return $t;
	}

	/**
	 * Enter description here...
	 *
	 * @param unknown_type $descriptors
	 * @return unknown
	 */
	public function add_descriptors ($descriptors = NULL, $append = true)
	{
		// no manual input of descriptors, get from DB
		if ( ! $this->descriptors) {
			$this->descriptors = array_keys($this->orm->table_columns);
		}

		// When $descriptors is a string, make it an array
		if (is_string($descriptors)) {
			$descriptors = array($descriptors);
		}

		if ($append) {
			$this->descriptors = array_merge($this->descriptors, $descriptors);
		} else {
			$this->descriptors = $descriptors;
		}
		return $this;
	}

	public function add_field_action ($fieldname, $action)
	{
		$this->field_actions[$fieldname] = $action;
		return $this;
	}

	public function add_actions ($actions)
	{
		$this->actions = (array) $actions;
		return $this;
	}

	private function filter_result ()
	{
		$this->filterquery = input::Instance()->post("filterquery");
		if ( ! empty($this->filterquery)) {
			$filterfor = array();
			foreach ($this->_searchable_array() as $t) {
				$filterfor[$t] = $this->filterquery;
			}
			$this->orm = $this->orm->orlike($filterfor);
		}
	}

	/**
	 * get method. Returns all html for whole index
	 *
	 * @return string
	 */
	public function get ()
	{
		$index = new View("kohadmin/kohadminindex/index");
		$this->filter_result();
		
		// set subtitle
		if (isset($this->title))
			$index->title = $this->title;
		
		// setting the CSS classes of the table
		$table_class = $this->table_type;		
		if ($this->defaults['sortable'])
			$table_class .= " sortable";
		$index->table_class = $table_class;

		if ($this->defaults['show_filter']) {
			$index->filter = $this->parse_filter();
		}
		$index->descriptors = $this->parse_descriptors();
		$index->rows = $this->parse_rows();
		// type casting needed for __toString function in calling view
		return (string) $index;
	}

	public function ignore_descriptors ($descriptors = NULL)
	{
		if (is_string($descriptors)) {
			$descriptors = array($descriptors);
		}
		$this->descriptors_ignore = $descriptors;

		return $this;
	}

	public function filter_ignores ($descriptors = NULL)
	{
		if (is_string($descriptors)) {
			$descriptors = array($descriptors);
		}
		$this->filter_ignores = $descriptors;

		return $this;
	}

	/**
	 * Create an array for rows in view
	 */
	private function parse_rows()
	{
		$return =  array();
		$orm_method = $this->orm_method;

		// retrieve all data
		if (isset($orm_method)) {
			$dataset = $this->orm->$orm_method();
		} else {
			$dataset = $this->orm->find_all();
		}

		foreach ($dataset as $data) {
			$row = array();
			// get all fields
			foreach ($this->_descriptors_array() as $descriptor) {
				if (array_key_exists($descriptor, $this->field_actions)) {
					if (is_array($this->field_actions[$descriptor])) {
						$field_action = $this->field_actions[$descriptor][0]."/".$this->field_actions[$descriptor][1]."/".$data->id;
					} else {
						$field_action = uri::segment(1)."/".$this->field_actions[$descriptor]."/".$data->id;
					}
				} else {
					$field_action = NULL;
				}
				$row[] = array(
					'value' 	=> $data->$descriptor,
					'action'	=> $field_action
				);
			}
			// add action if needed
			if (!empty($this->actions)) {
				foreach ($this->actions as $action) {
					$row[] = array(
						'value'		=> Kohana::lang("kohadmin.actions.".$action),
						'action'	=> uri::segment(1)."/".$action."/".$data->id
					);
				}
			}
			$return[] = $row;
		}
		return $return;
	}

	/**
	 * Build the view with the filter
	 *
	 * @return string
	 */
	private function parse_filter ()
	{
		$filter = new View("kohadmin/kohadminindex/filter");
		# get all descriptors which are searchable
		$t = array();
		foreach ($this->_searchable_array() as $descriptor) {
			if ( ! in_array($descriptor, $this->filter_ignores))
				$t[] = Kohana::lang("kohadminindex.descriptors.".$descriptor);
		}
		$filter->searchables = $t;
		$filter->filterquery = $this->filterquery;

		return $filter;
	}

	/**
	 * Create an array for descriptor view
	 *
	 * @return Array Keys: 'id', 'name' and 'class'
	 */
	private function parse_descriptors()
	{
		$return = array();
		foreach ($this->_descriptors_array() as $descriptor)
		{
			$return[] = array (
				'id'	=> $descriptor,
				'name' 	=> ucfirst(Kohana::lang("kohadminindex.descriptors.".$descriptor)),
				'class'	=> ""
			);
		}
		// add a field for additinal fields in data like 'actions'
		if (isset($this->actions))
			$return[] = array('name'=>'&nbsp;', 'class'=>'{sorter:false}');

		return $return;
	}

	/**
	 * Chainable method to set the way ORM must retrieve it's data
	 *
	 * @param String $method Name of method
	 * @return Object Return $this object
	 */
	public function set_orm_method ($method)
	{
		$this->orm_method = $method;
		return $this;
	}

	/**
	 * Chainable where wrapper for ORM
	 *
	 * @param unknown_type $key
	 * @param unknown_type $val
	 * @return unknown
	 */
	public function where ($key, $val)
	{
		$this->orm->where($key, $val);
		return $this;
	}
}
